package com.jc.platform.songjiajia.service.base.impl;

import com.jc.platform.songjiajia.mapper.IPartnerMapper;
import com.jc.platform.songjiajia.mapper.IPurchaseContractMapper;
import com.jc.platform.songjiajia.mapper.ISalesContractMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;




import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jc.platform.common.annotation.DataIsolation;
import com.jc.platform.common.constants.GlobalConstant;
import com.jc.platform.common.constants.StringPool;
import com.jc.platform.common.model.UserInfo;
import com.jc.platform.common.model.QueryParam;
import com.jc.platform.common.result.PageInfo;
import com.jc.platform.common.result.ResultCodeEnum;
import com.jc.platform.common.result.ResultModel;
import com.jc.platform.common.search.SqlUtils;
import com.jc.platform.common.utils.BeanUtil;
import com.jc.platform.common.utils.RequestUtil;
import com.jc.platform.songjiajia.vo.PartnerVO;
import com.jc.platform.songjiajia.entity.PartnerEntity;
import com.jc.platform.songjiajia.mapper.IPartnerMapper;
import com.jc.platform.songjiajia.service.base.impl.BaseServiceImpl;
import com.jc.platform.songjiajia.service.base.IBasePartnerService;
import com.jc.platform.mybatis.utils.CollectCovertUtil;
import com.jc.platform.mybatis.utils.ConditionUtil;
import org.springframework.beans.factory.annotation.Autowired;

import com.jc.platform.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.jc.platform.common.utils.CollectionUtil;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * ClassName AbstractPartnerServiceImpl.java
 * Description 合作单位
 *
 * @author songjiajia
 * @version 2.0
 * @date 2021/08/07
 */
@Slf4j
public abstract class AbstractPartnerServiceImpl extends BaseServiceImpl<PartnerVO> implements IBasePartnerService
{
	private static final String KEY_PREFIX = "db_platformSongjiajia:t_partner";

    @Autowired
    private RedisUtils<String, PartnerVO> redisUtils;
    @Autowired
    private IPartnerMapper partnerMapper;
    @Autowired
    private IPurchaseContractMapper purchaseContractMapper;
    @Autowired
    private ISalesContractMapper salesContractMapper;



	@Override
	public ResultModel<PartnerVO> insert(PartnerVO partnerVO)
	{
		PartnerEntity entity = new PartnerEntity();
		entity.copyFormVO(partnerVO);
		partnerMapper.insert(entity);

		partnerVO.setId(entity.getId());
		delRedisKeyBatch(KEY_PREFIX);
		return ResultModel.success(partnerVO);
	}

	@Override
	public ResultModel<PartnerVO> update(PartnerVO partner)
	{
		PartnerEntity entity = new PartnerEntity();
		entity.copyFormVO(partner);
		partnerMapper.updateById(entity);



		partner.setId(entity.getId());
		delRedisKeyBatch(KEY_PREFIX);
        delFromRedisAsync(entity.getId());
		entity = partnerMapper.selectById(entity.getId());
		return ResultModel.success(entity.copyToVO());
	}

    @Override
	public ResultModel<Boolean> remove(Long id)
	{
    
        PartnerEntity entity = partnerMapper.selectById(id);
        if (entity != null) {
            entity.setDeleted(true);
            partnerMapper.updateById(entity);
            delFromRedisAsync(entity.getId());
            delRedisKeyBatch(KEY_PREFIX);
        }
        return ResultModel.success(true);
    }

    @Override
	public ResultModel<Boolean> removeBatch(List<Long> ids)
	{
	    List<PartnerEntity> PartnerEntities = partnerMapper.selectBatchIds(ids);
        PartnerEntities.forEach(entity -> {
            entity.setId(entity.getId());
            entity.setDeleted(true);
            partnerMapper.updateById(entity);
            redisUtils.set(RedisUtils.getRedisKey(KEY_PREFIX, entity.getId()), entity.copyToVO());
        });

        ids.forEach(this::delFromRedisAsync);
        this.delColRedis();

        return ResultModel.success(true);
	}




	@Override
	public Boolean checkNotExists(Long id, String property, String value)
	{
        QueryWrapper<PartnerEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(BeanUtil.newInstance(PartnerEntity.class));
        queryWrapper.eq(SqlUtils.getColumnByProperty(property), value);

        if(id!=null && id>0){
            queryWrapper.ne(StringPool.ID, id);
        }

        queryWrapper.eq("deleted",false);

        return partnerMapper.selectCount(queryWrapper) <= 0;
	}

	@Override
	public ResultModel<PartnerVO> get(Long id)
	{
        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, id);
        PartnerVO partnerVO = getRedis(redisKey);
        if (partnerVO == null)
        {
            PartnerEntity entity = partnerMapper.selectById(id);
            if (entity == null){
                return ResultModel.failed();
            }
            partnerVO = entity.copyToVO();


            setRedis(redisKey, partnerVO);
        }
        return ResultModel.success(partnerVO);
	}

	@Override
	@DataIsolation(value = { "group_id","org_id","dept_id","create_id"})
	public ResultModel<List<PartnerVO>> find(QueryParam queryParam)
	{
		UserInfo userInfo = RequestUtil.getLoginUser();
		queryParam.getQuery().put("group_id",userInfo.getGroupId());
        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, "collection:find." + queryParam.toString());
        List<PartnerVO> list = getRedisForList(redisKey);
            if (list == null || list.isEmpty())
            {
                QueryWrapper<PartnerEntity> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, PartnerEntity.class);
                queryWrapper.eq("deleted",false);
                List<PartnerEntity> entities = partnerMapper.selectList(queryWrapper);
                list = CollectCovertUtil.listVO(entities);

                if (list != null && !list.isEmpty())
                {
                    setRedis(redisKey,list);
                }
            }
        return ResultModel.success(list);
	}

	@Override
	@DataIsolation(value = { "group_id","org_id","dept_id","create_id"})
	public ResultModel<PageInfo<PartnerVO>> finds(QueryParam queryParam)
	{
		UserInfo userInfo = RequestUtil.getLoginUser();
		queryParam.getQuery().put("group_id",userInfo.getGroupId());

        String redisKey = RedisUtils.getRedisKey(KEY_PREFIX, "collection:finds." + queryParam.toString());
        PageInfo<PartnerVO> page = getRedisForPage(redisKey);
        if (page == null)
        {
            QueryWrapper<PartnerEntity> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, PartnerEntity.class);
            queryWrapper.eq("deleted",false);
            IPage<PartnerEntity> entityPage = partnerMapper.selectPage(ConditionUtil.getPage(queryParam), queryWrapper);
            page = CollectCovertUtil.pageVO(entityPage);


            setRedis(redisKey,page);
        }
        return ResultModel.success(page);

	}

    @Override
	public ResultModel<Integer> count(QueryParam queryParam)
	{
        QueryWrapper<PartnerEntity> queryWrapper = ConditionUtil.getQueryWrapper(queryParam, PartnerEntity.class);
        Integer count = partnerMapper.selectCount(queryWrapper);
		return ResultModel.success(count);
	}



	@Override
	public ResultModel<List<PartnerVO>> importData(List<PartnerVO> partnerList) {
		List<PartnerEntity> saves = new ArrayList<>();
		List<PartnerVO> returnList = new ArrayList<>();
		for (PartnerVO partner : partnerList) {
			PartnerEntity entity = new PartnerEntity();
			entity.copyFormVO(partner);
			saves.add(entity);
		}
		saves.forEach(entity -> {
			partnerMapper.insert(entity);
			PartnerVO partner = entity.copyToVO();
			returnList.add(partner);
		});
		return ResultModel.success(partnerList);
	}




    private void delFromRedisAsync(Object id)
	{
		CompletableFuture.runAsync(() -> {
			try
			{
				TimeUnit.SECONDS.sleep(1);
				redisUtils.del(RedisUtils.getRedisKey(KEY_PREFIX, id));
			}
			catch (InterruptedException e)
			{
				log.error("缓存删除线程错误", e);
				Thread.currentThread()
					  .interrupt();
			}
		});
	}

	private void delColRedis()
	{
		String keyPattern = RedisUtils.getRedisKey(KEY_PREFIX, "collection:*");
		Set<String> keys = redisUtils.keys(keyPattern);
		if (keys != null)
		{
			String[] keyArray = keys.toArray(new String[] {});
			redisUtils.del(keyArray);
		}
	}
}

